package cn.iocoder.yudao.framework.business.order.service;

import cn.iocoder.yudao.framework.business.basic.dao.mapper.CoreMapper;
import cn.iocoder.yudao.framework.business.basic.dao.query.CoreQueryWrapper;
import cn.iocoder.yudao.framework.business.basic.service.impl.AbstractService;
import cn.iocoder.yudao.framework.business.order.dao.OrderMapper;
import cn.iocoder.yudao.framework.business.order.pojo.dto.OrderSubmitDTO;
import cn.iocoder.yudao.framework.business.order.pojo.po.OrderEntity;
import cn.iocoder.yudao.framework.business.order.pojo.vo.BizOrderVO;
import cn.iocoder.yudao.framework.business.order.pojo.vo.OrderSubmitVO;
import cn.iocoder.yudao.framework.common.exception.KnownServiceException;
import cn.iocoder.yudao.framework.common.exception.util.ServiceExceptionUtil;
import cn.iocoder.yudao.framework.common.pojo.PageResult;
import cn.iocoder.yudao.framework.common.util.object.BeanUtils;
import cn.iocoder.yudao.framework.constant.ErrorCodeConstants;
import cn.iocoder.yudao.framework.util.TransactionUtils;
import jakarta.annotation.Nonnull;
import lombok.extern.slf4j.Slf4j;
import org.springframework.transaction.annotation.Transactional;

/**
 * 订单 Service 实现类，由子类继承，子类标注 @{@link org.springframework.stereotype.Service}
 *
 * @author 山野羡民
 */
//@org.springframework.stereotype.Service
@Slf4j
public abstract class AppOrderBaseService<DO extends OrderEntity, RESP extends BizOrderVO, SAVE extends OrderSubmitDTO> extends AbstractService<DO, RESP> implements AppOrderService<RESP, SAVE> {

    @Override
    @Transactional(rollbackFor = Exception.class)
    public OrderSubmitVO submit(SAVE reqVO, Long userId) {
        long userIdNonnull = userId == null ? 0L : userId;
        DO order = onOrderCreateBefore(reqVO, userIdNonnull);
        order.setUserId(userIdNonnull);
        order.setPayed(false);
        getInjectedMapper().insert(order);
        // TODO 后续考虑重构，改为事件发布与监听模式：BizOrderCreatedMessage
        createPayOrder(order);
        onOrderCreateAfter(order);
        OrderSubmitVO respVO = new OrderSubmitVO();
        respVO.setTradeNo(order.getTradeNo());
        respVO.setPrice(order.getPrice());
        return respVO;
    }

    @Override
    public RESP getByTradeNo(String tradeNo) {
        CoreMapper<DO> mapper = getInjectedMapper();
        if (mapper instanceof OrderMapper<DO> orderBaseMapper) {
            DO order = orderBaseMapper.selectByTradeNo(tradeNo);
            return BeanUtils.toBean(order, resolveViewObjectClass());
        }
        throw new KnownServiceException("Mapper 必须是" + OrderMapper.class.getSimpleName() + " 的子类");
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public void checkAndUpdatePaid(String tradeNo, String payNo) {
        CoreMapper<DO> mapper = getInjectedMapper();
        if (mapper instanceof OrderMapper<DO> orderBaseMapper) {
            DO order = orderBaseMapper.selectByTradeNo(tradeNo);
            if (order == null) {
                log.warn("[checkAndUpdatePaid][tradeNo({}) 订单不存在 {}]", tradeNo, getInjectedMapper().getClass().getName());
                return;
            }
            if (Boolean.TRUE.equals(order.getPayed())) {
                log.warn("[checkAndUpdatePaid][tradeNo({}) 订单已经是已付款状态]", tradeNo);
                return;
            }
            // 若业务订单未支付，则从支付单中获取支付状态
            boolean paid = checkThirdPaid(tradeNo);
            if (!paid) {
                throw ServiceExceptionUtil.exception(ErrorCodeConstants.ORDER_UPDATE_PAID_PAY_ORDER_UNPAID);
            }
            // 若支付单中是已支付，则同步更新业务订单支付状态
            order.setPayed(true);
            order.setPayNo(payNo);
            onPaidBefore(order);
            getInjectedMapper().updateById(order);
            TransactionUtils.afterCommit(() -> {
                log.debug("[checkAndUpdatePaid][tradeNo({}) 订单支付成功，执行支付成功后续回调]", tradeNo);
                // 事务提交之后再回调，避免回调异常导致回滚
                onPaidAfter(order);
                return null;
            });
            return;
        }
        throw new KnownServiceException("Mapper 必须是" + OrderMapper.class.getSimpleName() + " 的子类");
    }

    /**
     * 订单创建前
     *
     * @param reqVO 提交订单的请求参数
     * @param userId 用户编号
     * @return 订单信息
     */
    @Nonnull
    protected abstract DO onOrderCreateBefore(@Nonnull SAVE reqVO, @Nonnull Long userId);

    /**
     * 订单创建后
     */
    protected void onOrderCreateAfter(@Nonnull DO ignoreOrder) {

    }

    /**
     * 创建付款单据
     *
     * @param order 业务订单
     */
    public abstract void createPayOrder(@Nonnull DO order);

    /**
     * 检查是否真的已支付，可以从第三方支付渠道（如微信支付）获取支付状态
     *
     * @param ignoreTradeNo 交易单号
     * @return 实际上是否真的支付成功
     */
    protected boolean checkThirdPaid(String ignoreTradeNo) {
        return true;
    }

    /**
     * 支付成功后，执行前置操作
     * @param ignoreOrder 订单信息
     */
    protected void onPaidBefore(DO ignoreOrder) {
    }

    /**
     * 支付成功后，执行后续操作
     * @param ignoreOrder 订单信息
     */
    protected void onPaidAfter(DO ignoreOrder) {
    }

    @Override
    public PageResult<RESP> getPage(Integer pageNo, Integer pageSize, Long userId) {
        CoreQueryWrapper<DO> wrapper = new CoreQueryWrapper<>();
        wrapper.eq("user_id", userId);
        return getPage(pageNo, pageSize, wrapper);
    }

}
